package com.nx.platform.es.biz.esspider.handler;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.nx.platform.es.biz.esspider.resource.DBManager;
import com.nx.platform.es.common.utils.MoreSplitters;
import com.nx.platform.es.biz.esspider.entity.Item;
import com.nx.platform.es.common.utils.MoreMaps;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

/**
 * 从数据库中获取单值字段过滤器(使用另一个Long类型的字段作为Key)
 *
 * @author
 * @since Mar 9, 2017
 */
@HandlerDefine(HandlerType.DB)
public class DBJoinLongFieldSingleValueHandler extends AbstractDBHandler {

    private static final Logger LOGGER = LogManager.getLogger(DBJoinLongFieldSingleValueHandler.class);
    private static final Gson GSON = new Gson();

    private String sql;
    private String joinField;
    private String[] field;
    private boolean factors;
    private boolean toString;

    public DBJoinLongFieldSingleValueHandler(String identity, DBManager dbManager) {
        super(identity, dbManager);
    }

    @Override
    public void init(Map<?, ?> settings) throws Exception {
        sql = MoreMaps.getString(settings, "sql");
        joinField = MoreMaps.getString(settings, "joinField");
        field = MoreMaps.getStringArray(settings, "field", MoreSplitters.COMMA);
        toString = MoreMaps.getBooleanValue(settings, "toString", false);
        factors = MoreMaps.getBooleanValue(settings, "factors", false);
        Preconditions.checkNotNull(getJdbcTemplate());
        Preconditions.checkArgument(!Strings.isNullOrEmpty(sql), "sql null or empty");
        Preconditions.checkArgument(!Strings.isNullOrEmpty(joinField), "idField null or empty");
        Preconditions.checkArgument(field != null && field.length > 0, "field null or empty");
    }

    @Override
    public void handle(Map<Long, Item> items) throws Exception {
        if (items.isEmpty()) {
            return;
        }
        // 建立ID到joinField的映射
        Map<Long, Long> id2JoinFieldMap = new HashMap<>(items.size());
        for (Entry<Long, Item> e : items.entrySet()) {
            Long joinFieldValue = MoreMaps.getLong(e.getValue().getDoc(), joinField);
            if (joinFieldValue != null) {
                id2JoinFieldMap.put(e.getKey(), joinFieldValue);
            }
        }
        LOGGER.debug(">>>> sql={}, id2JoinFieldMap={}", sql, id2JoinFieldMap);
        if (id2JoinFieldMap.isEmpty()) {
            return;
        }
        // 使用joinField查询数据库
        SqlParameterSource queryParams;
        if (toString) {
            queryParams = new MapSqlParameterSource(SQL_IDS_KEY,
                    id2JoinFieldMap.values().stream().map(String::valueOf).collect(Collectors.toList()));
        } else {
            queryParams = new MapSqlParameterSource(SQL_IDS_KEY, id2JoinFieldMap.values());
        }
        List<Map<String, Object>> queryResults = getJdbcTemplate().queryForList(sql, queryParams);
        LOGGER.debug(">>>> queryResults={}", queryResults);
        if (queryResults.isEmpty()) {
            return;
        }
        // 建立joinField查询结果映射
        Map<Long, Map<String, Object>> joinFieldValuesMap = new HashMap<>(queryResults.size());
        queryResults.forEach((Map<String, Object> queryResult) -> {
            Long joinFieldValue = MoreMaps.getLong(queryResult, joinField);
            if (joinFieldValue == null) {
                return;
            }
            for (String f : field) {
                Map<String, Object> valuesMap = joinFieldValuesMap.get(joinFieldValue);
                if (valuesMap == null) {
                    valuesMap = new HashMap<>(this.field.length);
                    joinFieldValuesMap.put(joinFieldValue, valuesMap);
                }
                Object value = queryResult.get(f);
                if (value instanceof BigInteger) {
                    value = ((BigInteger) value).longValue();
                }
                valuesMap.put(f, value);
            }
        });
        // ID到joinField的映射 + joinField查询结果映射
        for (Entry<Long, Item> e : items.entrySet()) {
            Long joinFieldValue = id2JoinFieldMap.get(e.getKey());
            if (joinFieldValue != null && joinFieldValuesMap.containsKey(joinFieldValue)) {
                Map<String, Object> joinFieldValues = joinFieldValuesMap.get(joinFieldValue);
                for (String f : field) {
                    String str = String.valueOf(joinFieldValues.get(f));
                    if (factors && str.startsWith("{") && str.endsWith("}")) {
                        try {
                            DBSingleValueFieldsHandler.ScoresFields fields = GSON.fromJson(str, DBSingleValueFieldsHandler.ScoresFields.class);
                            if (fields != null) {
                                e.getValue().getDoc().putAll(fields.toMap());
                            }
                        } catch (Throwable throwable) {
                            LOGGER.warn("read json field failed, id={}, json={}", e.getKey(), str, throwable);
                        }
                    } else {
                        e.getValue().getDoc().put(f, joinFieldValues.get(f));
                    }
                }
            }
        }
    }

}
